package cn.stylefeng.guns.modular.gridsystem.controller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.core.pojo.response.SuccessResponseData;
import cn.stylefeng.guns.modular.gridsystem.constants.GatewayTaskStatusConstant;
import cn.stylefeng.guns.modular.gridsystem.constants.GatewayTaskTypeConstant;
import cn.stylefeng.guns.modular.gridsystem.entity.*;
import cn.stylefeng.guns.modular.gridsystem.mapper.GatewayTaskMapper;
import cn.stylefeng.guns.modular.gridsystem.model.param.*;
import cn.stylefeng.guns.modular.gridsystem.model.result.*;
import cn.stylefeng.guns.modular.gridsystem.service.*;
import cn.stylefeng.guns.modular.gridsystem.utils.MyConst;
import cn.stylefeng.guns.modular.gridsystem.utils.MyFileUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.aivoicetech.wav.WavFeatureDetect;
import net.aivoicetech.wav.entity.WavFeature;
import org.apache.commons.io.FileUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ssy
 * @date 2022/1/13 15:00
 */
@RestController
@Slf4j
public class HomeController {

    @Resource
    private BizGatewayService bizGatewayService;

    @Resource
    private BizStationService bizStationService;

    @Resource
    private BizGatewayChannelService bizGatewayChannelService;

    @Resource
    private BizDeviceService bizDeviceService;

    @Resource
    private BizGatewayTypeService bizGatewayTypeService;

    @Resource
    private BizChannelTypeService bizChannelTypeService;

    @Resource
    private BizExceptionService bizExceptionService;

    @Resource
    private BizExceptionLogService bizExceptionLogService;

    @Resource
    private BizGatewayNewFileService bizGatewayNewFileService;

    @Resource
    private GatewayTaskService taskService;

    @Resource
    private BizUploadScoreService bizUploadScoreService;

    /**
     * 不同设备数量
     *
     * @return
     */
    @GetMapping("/index/getTypeCount")
    public ResponseData getTypeCount() {
        int stationCount = bizStationService.count();
        int gatewayCount = bizGatewayService.count();
        int channelCount = bizGatewayChannelService.count();
        int deviceCount = bizDeviceService.count();
        HashMap<String, Integer> map = MapUtil.newHashMap();
        map.put("stationCount", stationCount);
        map.put("gatewayCount", gatewayCount);
        map.put("channelCount", channelCount);
        map.put("deviceCount", deviceCount);
        return ResponseData.success(map);
    }

    @GetMapping("/index/getAllExceptionGroup")
    public ResponseData getAllExceptionGroup() {
        List<Map<String, Object>> allExceptionGroup = bizExceptionLogService.getAllExceptionGroup();
        ArrayList<String> exceptionGroupX = new ArrayList<>();
        ArrayList<Long> exceptionGroupY = new ArrayList<>();
        for (Map<String, Object> map : allExceptionGroup) {
            String errorName = String.valueOf(map.get("errorName"));
            exceptionGroupX.add(errorName);
            Object errorCount = map.get("errorCount");
            exceptionGroupY.add((Long) errorCount);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("exceptionGroupX", exceptionGroupX);
        map.put("exceptionGroupY", exceptionGroupY);
        return ResponseData.success(map);
    }

    @GetMapping("/index/getTopology")
    public ResponseData getTopology(Integer deviceId) {
        LambdaQueryWrapper<BizGatewayChannel> channelQueryWrapper = new LambdaQueryWrapper<>();
        channelQueryWrapper.eq(BizGatewayChannel::getDeviceId, deviceId);
        //根据设备查询通道
        List<BizGatewayChannel> channelList = bizGatewayChannelService.list(channelQueryWrapper);
        //获取对应的gatewayId
        Set<Integer> gatewayIds = new HashSet<>();
        for (BizGatewayChannel bizGatewayChannel : channelList) {
            Integer gatewayId = bizGatewayChannel.getGatewayId();
            gatewayIds.add(gatewayId);
        }
        Set<Map<String, Object>> gateways = new HashSet<>();
        for (Integer gatewayId : gatewayIds) {
            QueryWrapper<BizGateway> gatewayQueryWrapper = new QueryWrapper<>();
            gatewayQueryWrapper.select("id as gatewayId", "type_code as typeCode", "gateway_code as gatewayCode", "gateway_name as gatewayName", "updated_at as updatedAt", "status", "online_status as onlineStatus");
            gatewayQueryWrapper.eq("id", gatewayId);
            //查询网关
            Map<String, Object> gateway = bizGatewayService.getMap(gatewayQueryWrapper);
            gateway.put("id", "gatewayId" + gatewayId);
            gateway.put("gatewayId", gatewayId);
            gateway.put("type", "gateway");
            gateway.put("title", gateway.get("gatewayCode"));
            gateway.put("typeCode", gateway.get("typeCode"));
            LambdaQueryWrapper<BizGatewayChannel> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizGatewayChannel::getDeviceId, deviceId);
            queryWrapper.eq(BizGatewayChannel::getGatewayId, gatewayId);
            //查询网关的所有通道
            List<Map<String, Object>> list = bizGatewayChannelService.listMaps(queryWrapper);
            for (Map<String, Object> map : list) {
                String gatewayChannelId = map.get("id").toString();
                map.put("gatewayChannelId", gatewayChannelId);
                map.put("type", "gatewayChannel");
                map.put("channel", map.get("channel"));
                //查询通道类型
                QueryWrapper<BizChannelType> bizChannelTypeQueryWrapper = new QueryWrapper<>();
                bizChannelTypeQueryWrapper.eq("id", map.get("channel_type"));
                BizChannelType bizChannelType = bizChannelTypeService.getOne(bizChannelTypeQueryWrapper);

                //网关图片
                if (ObjectUtil.isNotNull(bizChannelType)) {
                    map.put("typeName", bizChannelType.getName());
                    map.put("model", bizChannelType.getModel());
                    map.put("background-image", "/upload/" + bizChannelType.getFileName());
                }
                map.put("title", map.get("channel"));
            }
            gateway.put("children", list);
            if (ObjectUtil.isNotNull(gateway)) {
                //查询网关类型
                QueryWrapper<BizGatewayType> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("code", gateway.get("typeCode"));
                BizGatewayType bizGatewayType = bizGatewayTypeService.getOne(queryWrapper1);
                //网关图片
                if (ObjectUtil.isNotNull(bizGatewayType)) {
                    gateway.put("fileName", bizGatewayType.getFileName());
                    gateway.put("background-image", "/upload/" + bizGatewayType.getFileName());
                }
                gateways.add(gateway);
            }
        }

        HashMap<String, Object> hashMap = new HashMap<>();
        //查询设备
        BizDeviceResult byId = bizDeviceService.queryById(deviceId);
        if (ObjectUtil.isNotNull(byId)) {
            // 设备图片
            hashMap.put("background-image", "/upload/" + byId.getFileName());
            hashMap.put("title", byId.getDeviceName());
            hashMap.put("device", byId);
        }
        hashMap.put("type", "device");
        hashMap.put("children", gateways);
        return ResponseData.success(hashMap);
    }

    @GetMapping("/index/getDeviceListByStationId")
    public ResponseData getDeviceListByStationId(Integer stationId) {
        BizDeviceParam deviceParam = new BizDeviceParam();
        deviceParam.setStationId(stationId);
        List<BizDeviceResult> list = bizDeviceService.list(deviceParam);
        return ResponseData.success(list);
    }

    @GetMapping("/index/getErrorCountByMonth")
    public ResponseData getErrorCountByMonth(Integer stationId) {
        List<ExceptionCountDataResult> map = bizExceptionService.getErrorCountByMonth(stationId);
        return ResponseData.success(map);
    }

    @GetMapping("/index/getChannelCount")
    public ResponseData getChannelCount(Integer stationId) {
        BizGatewayParam bizGatewayParam = new BizGatewayParam();
        bizGatewayParam.setStationId(stationId);
        List<GatewayResult> list = bizGatewayService.list(bizGatewayParam);
        ArrayList<Integer> gatewayIds = new ArrayList<>();
        for (GatewayResult bizGateway : list) {
            gatewayIds.add(bizGateway.getId());
        }
        Integer channelCount = bizGatewayChannelService.getChannelCount(gatewayIds);
        return ResponseData.success(channelCount);
    }

    @GetMapping("/index/getExceptionCountByStationId")
    public ResponseData getExceptionCountByStationId(Integer stationId) {
        BizGatewayParam bizGatewayParam = new BizGatewayParam();
        bizGatewayParam.setStationId(stationId);
        List<GatewayResult> list = bizGatewayService.list(bizGatewayParam);
        ArrayList<String> gatewayCodes = new ArrayList<>();
        for (GatewayResult bizGateway : list) {
            gatewayCodes.add(bizGateway.getGatewayCode());
        }
        List<Map<String, Object>> listMaps = bizExceptionLogService.getList(gatewayCodes);
        ArrayList<String> exceptionGroupX = new ArrayList<>();
        ArrayList<Long> exceptionGroupY = new ArrayList<>();
        for (Map<String, Object> map : listMaps) {
            String errorName = map.get("errorName").toString();
            exceptionGroupX.add(errorName);
            Object errorCount = map.get("errorCount");
            exceptionGroupY.add((Long) errorCount);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("exceptionGroupX", exceptionGroupX);
        map.put("exceptionGroupY", exceptionGroupY);
        return ResponseData.success(map);
    }

    @GetMapping("/index/getFaultRate")
    public ResponseData getFaultRate() {
        QueryWrapper<BizException> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("device_id as deviceId");
        queryWrapper.eq("status", 0);
        queryWrapper.groupBy("device_id");
        List<Map<String, Object>> count = bizExceptionService.listMaps(queryWrapper);
        int count1 = bizDeviceService.count();
        double faultSize = Double.parseDouble(String.valueOf(count.size()));
        double allSize = Double.parseDouble(String.valueOf(count1));
        double faultRate = 0;
        if (allSize != 0) {
            BigDecimal b = BigDecimal.valueOf((faultSize / allSize) * 100);
            faultRate = b.setScale(2, RoundingMode.HALF_UP).doubleValue();
        }
        return ResponseData.success(faultRate);
    }

    @PostMapping("/index/getBuffer")
    public ResponseData getBuffer(@RequestPart(value = "file") MultipartFile file) throws Exception {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件后缀
        String prefix = null;
        if (fileName != null) {
            prefix = fileName.substring(fileName.lastIndexOf("."));
        }
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码
        File fileTemp = File.createTempFile(Objects.requireNonNull(fileName), prefix);
        FileUtils.copyInputStreamToFile(file.getInputStream(), fileTemp);
        WavFeatureDetect wavFeatureDetect = WavFeatureDetect.build(WavFeatureDetect.FeatureType.Spectrogram);
        List<WavFeature> feature = wavFeatureDetect.getFeature(fileTemp);
//        for (WavFeature wavFeature:feature){
//            System.out.println(wavFeature.getData());
//        }
        return ResponseData.success(feature);
    }

    @PostMapping("/index/getBufferByPath")
    public ResponseData getBufferByPath(String fileName) throws Exception {
        String path = (MyFileUtils.getUploadPath() + fileName.replace("/upload", "")).trim().replaceAll("//", "/");
        File file = new File(path);
        if (!file.exists()) {
            return ResponseData.error("故障文件不存在");
        }
        WavFeatureDetect wavFeatureDetect = WavFeatureDetect.build(WavFeatureDetect.FeatureType.Spectrogram);
        List<WavFeature> feature = wavFeatureDetect.getFeature(file);
        return ResponseData.success(feature);
    }

    @PostMapping("/index/getData")
    public ResponseData getData(String fileName) throws Exception {
        String path = (MyFileUtils.getUploadPath() + fileName).trim().replaceAll("//", "/");
        File file = new File(path);
        if (!file.exists()) {
            return ResponseData.error("故障文件不存在");
        }
        WavFeatureDetect wavFeatureDetect = WavFeatureDetect.build(WavFeatureDetect.FeatureType.SoundWav, WavFeatureDetect.FeatureType.FREQUENCY, WavFeatureDetect.FeatureType.SoundPressLevel, WavFeatureDetect.FeatureType.Spectrogram);
        List<WavFeature> wavFeatureList = wavFeatureDetect.getFeature(file);
        ArrayList<Map<String, Object>> arrayList = new ArrayList<>();
        for (WavFeature wavFeature : wavFeatureList) {
            ArrayList data = (ArrayList) wavFeature.getData();
            final float stepTimeLength = wavFeature.getStepTimeLength();
            double[] subscript = new double[data.size()];
            if (wavFeature.getType().equals(WavFeatureDetect.FeatureType.SoundPressLevel.toString())) {
                for (int j = 0; j < data.size(); j++) {
                    subscript[j] = Math.floor(((j * stepTimeLength)/1000)*10)/10;
                    data.set(j, Double.parseDouble(data.get(j).toString()) + 100);
                }
            } else {
                for (int j = 0; j < data.size(); j++) {
                    subscript[j] = Math.floor(((j * stepTimeLength)/1000)*10)/10;
                }
            }
            HashMap<String, Object> map = new HashMap<>();
            map.put("xData", subscript);
            map.put("yData", data);
            arrayList.add(map);

        }
        return ResponseData.success(arrayList);
    }

    @GetMapping("/index/getTreeList")
    public ResponseData getTreeList() {
        List<BizStationResult> stationList = bizStationService.list(new BizStationParam());
        List<Map<String, Object>> list = new ArrayList<>();
        for (BizStationResult bizStation : stationList) {
            Integer stationId = bizStation.getId();
            String stationName = bizStation.getStationName();
            Map<String, Object> stationMap = new HashMap<>();

            BizGatewayParam bizGatewayParam = new BizGatewayParam();
            bizGatewayParam.setStationId(stationId);
            List<GatewayResult> gatewayList = bizGatewayService.list(bizGatewayParam);
            List<Map<String, Object>> gList = new ArrayList<>();

            for (GatewayResult bizGateway : gatewayList) {
                Integer gatewayId = bizGateway.getId();
                String gatewayCode = bizGateway.getGatewayCode();

                BizGatewayChannelParam channelParam = new BizGatewayChannelParam();
                channelParam.setGatewayId(gatewayId);
                List<BizGatewayChannelResult> channelList = bizGatewayChannelService.list(channelParam);
                List<Map<String, Object>> cList = new ArrayList<>();

                for (BizGatewayChannelResult bizGatewayChannel : channelList) {
                    Integer channelId = bizGatewayChannel.getId();
                    String channel = bizGatewayChannel.getChannel();
                    Map<String, Object> channelMap = new HashMap<>();
                    channelMap.put("value", channelId);
                    channelMap.put("label", channel);
                    cList.add(channelMap);
                }

                Map<String, Object> gatewayMap = new HashMap<>();
                gatewayMap.put("value", gatewayId);
                gatewayMap.put("label", gatewayCode);
                gatewayMap.put("children", cList);
                gList.add(gatewayMap);
            }
            stationMap.put("value", stationId);
            stationMap.put("label", stationName);
            stationMap.put("children", gList);
            list.add(stationMap);

        }
        return ResponseData.success(list);
    }

    /**
     * 获取对应设备的通道的最新故障
     *
     * @param deviceId
     * @return
     */
    @GetMapping("/index/exceptionLogGroupByRouter")
    public ResponseData exceptionLogGroupByRouter(Integer deviceId) {
        List<Map<String, Object>> list = bizExceptionLogService.groupByRouterList(deviceId);
        return new SuccessResponseData(list);
    }

    /**
     * 获取设备最近7天的分数趋势图
     *
     * @param deviceId
     * @return
     */
    @GetMapping("/index/getExceptionLately")
    public ResponseData getExceptionLately(Integer deviceId) {
        List<BizUploadScore> list = bizUploadScoreService.getScoresLately(deviceId);
        return new SuccessResponseData(list);
    }

    /**
     * 获取网关对应通道的最新文件信息
     *
     * @return
     */
    @GetMapping("/index/getGatewayChannelNewFile")
    public ResponseData getGatewayChannelNewFile(String gatewayCode, String channel) {
        final BizGatewayParam gatewayParam = new BizGatewayParam();
        gatewayParam.setGatewayCode(gatewayCode);
        final BizGateway bizGateway = bizGatewayService.gatewayByGatewayCode(gatewayParam);
        if (ObjectUtil.isNull(bizGateway)) {
            throw new ServiceException(MyConst.GATEWAY_NOT_EXIST);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("micRouter", channel);

        List<Integer> gatewayIds = new ArrayList<>();
        gatewayIds.add(bizGateway.getId());
        taskService.add(GatewayTaskTypeConstant.UPLOAD_NEW_FILE, gatewayIds, JSONUtil.toJsonStr(map));
        log.info("下发获取{}通道最新文件任务",channel);
        BizGatewayNewFileResult bizGatewayNewFile = bizGatewayNewFileService.getGatewayChannelNewFile(gatewayCode, channel);
        return new SuccessResponseData(bizGatewayNewFile);
    }

    //
    /**
     * <p>站点对应的网关树信息</p >
     * @param param
     */
    @GetMapping("/index/station/gatewayTree")
    public ResponseData newTree(BizStationParam param) {
        List<BizStationResult> list = bizStationService.list(param);
        List<Integer> stationIds = list.stream().map(BizStationResult::getId).collect(Collectors.toList());

        List<BizGateway> gatewayList = bizGatewayService.lambdaQuery().in(BizGateway::getStationId, stationIds).list();

        List<TreeParamVo> treeParamList = new ArrayList<>();

        for (BizStationResult stationResult : list) {
            TreeParamVo treeParam = new TreeParamVo();
            treeParam.setId(stationResult.getId().toString());
            treeParam.setLabel(stationResult.getStationName());
            treeParam.setGrade(1);
            treeParam.setChildren(childrenTree(gatewayList,stationResult.getId()));
            treeParamList.add(treeParam);
        }
        return new SuccessResponseData(treeParamList);
    }

    public  List<TreeParamVo> childrenTree(List<BizGateway> gatewayList, Integer id) {

        List<TreeParamVo> treeParamList = new ArrayList<>();
        for (BizGateway gateway : gatewayList) {
            if(id.equals(gateway.getStationId())){
                TreeParamVo treeParam = new TreeParamVo();
                treeParam.setId(gateway.getGatewayCode());
                treeParam.setLabel(gateway.getGatewayName());
                treeParamList.add(treeParam);
            }
        }
        return treeParamList;
    }




}
